home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / SciAn / src / ScianPerspec.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  31KB  |  1,184 lines

  1. /* ScianPerspec.c:    John R. Murray, 3-30-90
  2.         creates and deals with perspective Controls
  3. */
  4. #include "Scian.h"
  5. #include "ScianTypes.h"
  6. #include "ScianColors.h"
  7. #include "ScianIDs.h"
  8. #include "ScianWindows.h"
  9. #include "ScianObjWindows.h"
  10. #include "ScianErrors.h"
  11. #include "ScianEvents.h"
  12. #include "ScianScripts.h"
  13. #include "ScianButtons.h"
  14. #include "ScianPerspec.h"
  15. #include "ScianArrays.h"
  16. #include "ScianControls.h"
  17. #include "ScianIcons.h"
  18. #include "ScianDraw.h"
  19. #include "ScianObjFunctions.h"
  20. #include "ScianSnap.h"
  21.  
  22. /* globals */
  23. ObjPtr    perspecControlClass;            /* class of perspecControl */
  24.  
  25. /* temporary defs to get something going */
  26.  
  27. /* none */
  28.  
  29. /* local constants */
  30. #define MY_PI        3.14159
  31. #define BUTTONHEIGHT    4    /* button "height"=width (pixels) of border) */
  32.  
  33. /* internal drawing things and fudges */
  34. #define PERSPECBORDER    8.0
  35. #define RECWIDTH    15.0
  36. #define RECDEPTH    7.0
  37. #define RECSIZE        (RECDEPTH+RECWIDTH)
  38. #define TOPFUDGE    RECSIZE
  39. #define SIDEFUDGE    RECSIZE
  40. #define BOTTOMFUDGE    RECSIZE + 20.0
  41. #define CLIPLINELENGTH    50.0
  42. #define SLOP        30.0
  43. #define ANGLESLOP    6.0
  44. #define ORTHOSLOP    ((MAXORTHOFOV - MINORTHOFOV) / 20.0)
  45. #define PERSPECSCALE .1
  46. #define MINCLIPDELTA    0.01
  47.  
  48. ObjPtr    DrawPerspecControl(theControl)
  49. ObjPtr    theControl;
  50. {
  51. #ifdef GRAPHICS
  52.     int    left, right, bottom, top;
  53.     ObjPtr    theLabel;
  54.     char    *label;
  55.     ObjPtr    valuesArray, hilitesArray, locArray;
  56.     real    values[4], hilites[4], loc[2];
  57.     real    eyeDist, fov, nearClip, farClip;
  58.     Coord    v[4][2];
  59.     real    xPos, yPos;
  60.     int        iX, iY;
  61.     real    xRel, yRel;
  62.     real    fudgeScale;
  63.     int        color;
  64.  
  65.     /* get bounds, and draw control background */
  66.     if (!Get2DIntBounds(theControl, &left, &right, &bottom, &top))
  67.     {
  68.         return NULLOBJ;
  69.     }
  70.  
  71.     if (IsDrawingRestricted(left, right, bottom, top))
  72.     {
  73.     return ObjFalse;
  74.     }
  75.  
  76.     valuesArray = GetFixedArrayVar("DrawPerspecControl", theControl,
  77.                     VALUE, 1, 4L);
  78.     hilitesArray = GetFixedArrayVar("DrawPerspecControl", theControl,
  79.                     HIGHLIGHTED, 1, 4L);
  80.     locArray = GetFixedArrayVar("DrawPerspecControl", theControl,
  81.                     ICONLOC, 1, 2L);
  82.     if (!valuesArray || !hilitesArray || !locArray)
  83.     {
  84.     return NULLOBJ;
  85.     }
  86.  
  87.     Array2CArray(values, valuesArray);
  88.     eyeDist = values[0];
  89.     fov = values[1];
  90.     nearClip = values[2];
  91.     farClip = values[3];
  92.     Array2CArray(hilites, hilitesArray);
  93.     Array2CArray(loc, locArray);
  94.  
  95.     DrawRaisedRect(left, right, bottom, top, UIBACKGROUND);
  96.  
  97.     /* draw everything else */
  98.     yPos = (int) (bottom + BOTTOMFUDGE
  99.            + eyeDist * ((top - TOPFUDGE) - (bottom + BOTTOMFUDGE))
  100.              / (MAXEYEDIST - MINEYEDIST));
  101.     xPos = (int) (left + (right - left) / 2);
  102.     iY = yPos;
  103.     iX = xPos;
  104.  
  105.     if ((int) hilites[0])
  106.     {
  107.     SetUIColor(UIGRAY25);
  108.     }
  109.     else
  110.     {
  111.     SetUIColor(UITEXT);
  112.     }
  113.  
  114.     /* Draw icon-like central figure */
  115. #if 0
  116.     move2(xPos,yPos);  /* center of figure */
  117.     rmv2(4.0, 4.0);        /* +4, +4 */
  118.     rdr2(-RECWIDTH, 0.0);    /* +4-RW, +4 */
  119.     rdr2(0.0, -RECWIDTH);    /* +4-RW, +4-RW */
  120.     rdr2(RECWIDTH, 0.0);    /* +4, +4-RW */
  121.     rdr2(0.0, RECWIDTH);    /* +4, +4 */
  122.     rdr2(RECDEPTH, RECDEPTH);    /* +4+RD, +4+RD */
  123.     rdr2(-RECWIDTH, 0.0);    /* +4+RD-RW, +4+RD */
  124.     rdr2(0.0, -RECWIDTH);    /* +4+RD-RW, +4+RD-RW */
  125.     rdr2(RECWIDTH, 0.0);    /* +4+RD, +4+RD-RW */
  126.     rdr2(0.0, RECWIDTH);    /* +4+RD, +4+RD */
  127.     rmv2(-RECWIDTH, 0.0);    /* mmm +4+RD-RW, +4+RD */
  128.     rdr2(-RECDEPTH, -RECDEPTH);    /* +4-RW, +4 */
  129.     rmv2(0.0, -RECWIDTH);    /* mmm +4-RW, +4-RW */
  130.     rdr2(RECDEPTH, RECDEPTH);    /* +4+RD-RW, +4+RD-RW */
  131.     rmv2(RECWIDTH, 0.0);    /* mmm +4+RD, +4+RD-RW */
  132.     rdr2(-RECDEPTH, -RECDEPTH);    /* +4, +4-RW */
  133. #else
  134.     iX += 4;
  135.     iY += 4;
  136.  
  137.     DrawLine(iX, iY, iX, iY - RECWIDTH);
  138.     DrawLine(iX - RECWIDTH, iY, iX - RECWIDTH, iY - RECWIDTH);
  139.     DrawLine(iX, iY, iX - RECWIDTH, iY);
  140.     DrawLine(iX, iY - RECWIDTH, iX - RECWIDTH, iY - RECWIDTH);
  141.  
  142.     DrawLine(iX + RECDEPTH, iY + RECDEPTH, iX + RECDEPTH, iY + RECDEPTH - RECWIDTH);
  143.     DrawLine(iX + RECDEPTH - RECWIDTH, iY + RECDEPTH, iX + RECDEPTH - RECWIDTH, iY + RECDEPTH - RECWIDTH);
  144.     DrawLine(iX + RECDEPTH, iY + RECDEPTH, iX + RECDEPTH - RECWIDTH, iY + RECDEPTH);
  145.     DrawLine(iX + RECDEPTH, iY + RECDEPTH - RECWIDTH, iX + RECDEPTH - RECWIDTH, iY + RECDEPTH - RECWIDTH);
  146.  
  147.     DrawLine(iX, iY, iX + RECDEPTH, iY + RECDEPTH);
  148.     DrawLine(iX - RECWIDTH, iY, iX + RECDEPTH - RECWIDTH, iY + RECDEPTH);
  149.     DrawLine(iX - RECWIDTH, iY - RECWIDTH, iX + RECDEPTH - RECWIDTH, iY + RECDEPTH - RECWIDTH);
  150.     DrawLine(iX, iY - RECWIDTH, iX + RECDEPTH, iY + RECDEPTH - RECWIDTH);
  151. #endif
  152.  
  153.     /* Draw near-clip and far-clip lines */
  154.     yPos = (int) (bottom + BOTTOMFUDGE
  155.            + nearClip * ((top - TOPFUDGE) - (bottom + BOTTOMFUDGE))
  156.                          / (MAXEYEDIST - MINEYEDIST));
  157.     xPos = (int) (left + (right - left) / 2);
  158.     iX = xPos;
  159.     iY = yPos;
  160.  
  161.     if ((int) hilites[2])
  162.     {
  163.     SetUIColor(UIGRAY12);
  164.     }
  165.     else
  166.     {
  167.     SetUIColor(UITEXT);
  168.     }
  169. #if 0
  170.     move2(xPos, yPos);
  171.     rmv2(-CLIPLINELENGTH/2, 0.0);
  172.     rdr2(CLIPLINELENGTH, 0.0);
  173.     if ((int) hilites[2])
  174.     {
  175.     rmv2(0,1);
  176.     rdr2(-CLIPLINELENGTH, 0);
  177.     rmv2(0,-2);
  178.     rdr2(CLIPLINELENGTH, 0);
  179.     }
  180. #else
  181.     DrawLine(iX - CLIPLINELENGTH/2, iY, iX + CLIPLINELENGTH/2, iY);
  182.     if ((int) hilites[2])
  183.     {
  184.     DrawLine(iX - CLIPLINELENGTH/2, iY+1, iX + CLIPLINELENGTH/2, iY+1);
  185.     DrawLine(iX - CLIPLINELENGTH/2, iY-1, iX + CLIPLINELENGTH/2, iY-1);
  186.     }
  187. #endif
  188.     yPos = (int) (bottom + BOTTOMFUDGE
  189.            + farClip * ((top - TOPFUDGE) - (bottom + BOTTOMFUDGE))
  190.                         / (MAXEYEDIST - MINEYEDIST));
  191.     xPos = (int) (left + (right - left) / 2);
  192.     iX = xPos;
  193.     iY = yPos;
  194.  
  195.     if ((int) hilites[3])
  196.     {
  197.     SetUIColor(UIGRAY12);
  198.     }
  199.     else
  200.     {
  201.     SetUIColor(UITEXT);
  202.     }
  203. #if 0
  204.     move2(xPos, yPos);
  205.     rmv2(-CLIPLINELENGTH/2, 0.0);
  206.     rdr2(CLIPLINELENGTH, 0.0);
  207.     if ((int) hilites[3])
  208.     {
  209.     rmv2(0,1);
  210.     rdr2(-CLIPLINELENGTH, 0);
  211.     rmv2(0,-2);
  212.     rdr2(CLIPLINELENGTH, 0);
  213.     }
  214. #else
  215.     DrawLine(iX - CLIPLINELENGTH/2, iY, iX + CLIPLINELENGTH/2, iY);
  216.     if ((int) hilites[3])
  217.     {
  218.     DrawLine(iX - CLIPLINELENGTH/2, iY+1, iX + CLIPLINELENGTH/2, iY+1);
  219.     DrawLine(iX - CLIPLINELENGTH/2, iY-1, iX + CLIPLINELENGTH/2, iY-1);
  220.     }
  221. #endif
  222.  
  223.     /* Draw field-of-view lines */
  224.     if ((int) hilites[1])
  225.     {
  226.     SetUIColor(UIGRAY12);
  227.     }
  228.     else
  229.     {
  230.     SetUIColor(UITEXT);
  231.     }
  232.  
  233. /* (((b[1]-SF)-(b[0]+SF))/2.0)) * fov / MAXO = mX-(b[0]+b[1])/2.0 */
  234.  
  235.     if (GetPredicate(theControl, ORTHO))
  236.     {
  237.     real xOff;
  238.     /*draw width of ortho view lines */
  239.     xOff = fov / MAXORTHOFOV * ((right - SIDEFUDGE) - (left + SIDEFUDGE)) / 2.0;
  240. #if 0
  241.     move2((left + right) / 2 + xOff, bottom + BOTTOMFUDGE);
  242.     draw2((left + right) / 2 + xOff, top - TOPFUDGE);
  243. #else
  244.     DrawLine((left + right) / 2 + xOff, bottom + BOTTOMFUDGE,
  245.          (left + right) / 2 + xOff, top - TOPFUDGE);
  246. #endif
  247.     if ((int) hilites[1])
  248.     {
  249. #if 0
  250.         move2((left + right) / 2 + xOff + 1, bottom + BOTTOMFUDGE);
  251.         draw2((left + right) / 2 + xOff + 1, top - TOPFUDGE);
  252. #else
  253.         DrawLine((left + right) / 2 + xOff + 1, bottom + BOTTOMFUDGE,
  254.                  (left + right) / 2 + xOff + 1, top - TOPFUDGE);
  255. #endif
  256.     }
  257. #if 0
  258.         move2((left + right) / 2 - xOff, bottom + BOTTOMFUDGE);
  259.         draw2((left + right) / 2 - xOff, top - TOPFUDGE);
  260. #else
  261.         DrawLine((left + right) / 2 - xOff, bottom + BOTTOMFUDGE,
  262.              (left + right) / 2 - xOff, top - TOPFUDGE);
  263. #endif
  264.         if ((int) hilites[1])
  265.         {
  266. #if 0
  267.             move2((left + right) / 2 - xOff - 1, bottom + BOTTOMFUDGE);
  268.             draw2((left + right) / 2 - xOff - 1, top - TOPFUDGE);
  269. #else
  270.             DrawLine((left + right) / 2 - xOff - 1, bottom + BOTTOMFUDGE,
  271.                      (left + right) / 2 - xOff - 1, top - TOPFUDGE);
  272. #endif
  273.         }
  274.     }
  275.     else
  276.     {
  277.     /* draw angle of perspective view lines */
  278.     xPos = (int) (left + (right - left) / 2);
  279.     yPos = (int) (bottom + BOTTOMFUDGE);
  280. #if 0
  281.     move2(xPos, yPos);
  282. #endif
  283.     xRel = rsin(MY_PI * (fov/2.0)/180.0);
  284.     yRel = rcos(MY_PI * (fov/2.0)/180.0);
  285.     if (xRel / yRel >= ((right - PERSPECBORDER) - xPos)
  286.                  / ((top - PERSPECBORDER) - yPos))
  287.     {
  288.         fudgeScale = ((right - PERSPECBORDER) - xPos) / xRel;
  289.         xRel = xRel * fudgeScale; /* should end up being xPos - left */
  290.         yRel = yRel * fudgeScale;
  291.     }
  292.     else
  293.     {
  294.         fudgeScale = ((top - PERSPECBORDER) - yPos) / yRel;
  295.         yRel = yRel * fudgeScale;
  296.         xRel = xRel * fudgeScale;
  297.     }
  298. #if 0
  299.     rdr2(xRel, yRel);
  300.     if ((int) hilites[1])
  301.     {
  302.         rmv2(1,0);
  303.         rdr2(-xRel, -yRel);
  304.     }
  305.     move2(xPos, yPos);
  306.     rdr2(-xRel, yRel);
  307.     if ((int) hilites[1])
  308.     {
  309.         rmv2(-1,0);
  310.         rdr2(xRel, -yRel);
  311.     }
  312. #else
  313.     if ((int) hilites[1])
  314.     {
  315.         SetLineWidth(2);
  316.     }
  317.  
  318.     DrawLine(xPos, yPos, xPos + xRel, yPos + yRel);
  319.     DrawLine(xPos, yPos, xPos - xRel, yPos + yRel);
  320.  
  321.     if ((int) hilites[1])
  322.     {
  323.         SetLineWidth(1);
  324.     }
  325. #endif
  326.     }
  327.  
  328.     if (GetVar(theControl, COLOR))
  329.     {
  330.     color = GetInt(GetIntVar("DrawIconButtonObj", theControl, COLOR));
  331.     }
  332.     else
  333.     {
  334.     color = UIBACKGROUND;
  335.     }
  336.  
  337.     if (GetVar(theControl, LABEL))
  338.     {
  339.     label = GetString(GetStringVar("DrawIconButtonObj", theControl, LABEL));
  340.     }
  341.     else
  342.     {
  343.     label = (char *) NIL;
  344.     }
  345.  
  346.     /* Draw the Eye */
  347.     DrawIcon((left + right) / 2 + loc[0], bottom + BOTTOMFUDGE/2.0 + loc[1], 
  348.     GetInt(GetIntVar("DrawIconButtonObj", theControl, WHICHICON)),
  349.     label, (char *) NIL, color,
  350.     DI_DRAWFORE | DI_DRAWBACK | DI_SMALLTEXT);
  351.     return NULLOBJ;
  352.  
  353. #endif /* GRAPHICS */
  354. }
  355.  
  356. void Eyeball(left, right, bottom, top, xPos, yPos)
  357. int left, right, bottom, top;
  358. real xPos, yPos;
  359. {
  360.  
  361. #ifdef GRAPHICS
  362. #if 0
  363.     /* Draw THE EYEBALL!!! */
  364.     xPos = left + (right - left) / 2;
  365.     yPos = bottom + BOTTOMFUDGE/2.0;
  366.     SetUIColor(UITEXT);
  367.     move2(xPos, yPos);
  368.     rdr2(1,0);
  369.     rdr2(0,1);
  370.     rdr2(-1, 0);
  371.     rdr2(0,-1);
  372.     rmv2(-1,-1);
  373.     rdr2(1,-1);
  374.     rdr2(1, 0);
  375.     rdr2(2, 2);
  376.     rdr2(0, 1);
  377.     rdr2(-2,2);
  378.     rdr2(-1,0);
  379.     rdr2(-2,-2);
  380.     rdr2(0,-1);
  381.     rmv2(0,4);
  382.     rdr2(-2, -2);
  383.     rdr2(0, -3);
  384.     rdr2(3,-3);
  385.     rdr2(3,0);
  386.     rdr2(3,3);
  387.     rdr2(0,3);
  388.     rdr2(-2,2);
  389.     rdr2(0,4);
  390.     rdr2(-5,0);
  391.     rdr2(0,-4);
  392.     rmv2(-3,0);
  393.     rdr2(11,0);
  394.     SetUIColor(UIRED);
  395.     move2(xPos - 1, yPos + 3);
  396.     rdr2(-2,-2);
  397.     rdr2(0,-1);
  398.     rdr2(3,-3);
  399.     rdr2(1,0);
  400.     rdr2(3,3);
  401.     rdr2(0,1);
  402.     rdr2(-2,2);
  403.     rdr2(1,0);
  404.     rdr2(0,-3);
  405.     rdr2(-2,-2);
  406.     rdr2(-3,0);
  407.     rdr2(-2,2);
  408.     rdr2(0,3);
  409.     rdr2(1,1);
  410. #endif
  411. #endif /* GRAPHICS */
  412. }
  413.  
  414. ObjPtr    PressPerspecControl(theControl, mouseX, mouseY, flags)
  415. ObjPtr    theControl;
  416. int     mouseX, mouseY;
  417. int             flags;
  418. {
  419. #ifdef INTERACTIVE
  420.     int        mX, mY, mXold, mYold;    /* mouse X and Y returned by Mouse()*/
  421.     int        deltaX, deltaY;        /* change from initial X and Y */
  422.     int        bounds[4];              /* meat of boundsArray */
  423.     ObjPtr    valuesArray;        /* array of data for complex control */
  424.     real    values[4];        /* meat of valuesArray */
  425.     real    oldValues[4];        /* old meat of valuesArray */
  426.     real    saveValues[4];        /* old meat of valuesArray */
  427.     int         isChanged;              /* return value of changer */
  428.     ObjPtr    hilitesArray;        /* ptr to hilites values for parts */
  429.     real    hilites[4];        /* meat of hilites values array */
  430.     int        i;            /* loop counter */
  431.     int        which;            /* which control part we're moving */
  432.     real    tempvalue;        /* temp. holder for value swapping */
  433.     real    nearYPos, farYPos;    /* calculation temporaries */
  434.     Bool    ortho;            /* value of GetPredicate(obj, ORTHO) */
  435.     Bool    hiResMode = false;    /* true iff user wants hi mouse res. */
  436.     real    clipOff1, clipOff2;    /* offsets of clip planes from object*/
  437.  
  438.     if (!Get2DIntBounds(theControl,&bounds[0],&bounds[1],&bounds[2],&bounds[3]))
  439.     {
  440.         return ObjFalse;
  441.     }
  442.     valuesArray = GetFixedArrayVar("PressPerspecControl",theControl,VALUE,1,4L);
  443.     hilitesArray = GetFixedArrayVar("PressPerspecControl",theControl,HIGHLIGHTED,1,4L);
  444.     if (valuesArray && hilitesArray)
  445.     {
  446.     Array2CArray(values, valuesArray);
  447.     Array2CArray(hilites, hilitesArray);
  448.     }
  449.     else
  450.     {
  451.         return ObjFalse;
  452.     }
  453.  
  454.     /* test if mouse in my rectangle */
  455.     if (mouseX < bounds[0] || mouseX > bounds[1] ||
  456.         mouseY < bounds[2] || mouseY > bounds[3])
  457.     {
  458.         /* mouse out of my rectangle, do nothing, return */
  459.         return ObjFalse;
  460.     }
  461.  
  462.     /* test for helpclick */
  463.     if (TOOL(flags) == T_HELP)
  464.     {
  465.     ContextHelp(theControl);
  466.     return ObjTrue;
  467.     }
  468.  
  469.     /* it's really a click, and not out of bounds, and not a helpclick */
  470.  
  471.     SaveForUndo(theControl);
  472.  
  473.     if (ShiftDown())
  474.     {
  475.     hiResMode = true;
  476.     }
  477.  
  478.     for (i=0; i<4; ++i)
  479.     saveValues[i] = oldValues[i] = values[i];
  480.  
  481.     ortho = GetPredicate(theControl, ORTHO);
  482.  
  483.     /* determine which part is moving */
  484.     if (ABS(mouseX - (bounds[0] + bounds[1])/2) < RECSIZE/2
  485.     && ABS(mouseY - (bounds[2] + BOTTOMFUDGE
  486.         + values[0] * ((bounds[3]-TOPFUDGE) - (bounds[2]+BOTTOMFUDGE))
  487.                  / (MAXEYEDIST - MINEYEDIST))) < RECSIZE/2)
  488.     {
  489.     /* changing the eyeDistance */
  490.     which = 0;
  491.     clipOff1 = values[2] - values[0];
  492.     clipOff2 = values[3] - values[0];
  493.     }
  494.     else if (ortho && ORTHOSLOP >
  495.         ABS(values[1] - ABS(MAXORTHOFOV *
  496.         (mouseX - (bounds[0] + bounds[1])/2.0)
  497.         / ( ((bounds[1]-SIDEFUDGE)-(bounds[0]+SIDEFUDGE)) / 2.0))))
  498.     {
  499.     /* changing the orthogonal field of view */
  500.     which = 1;
  501.     }
  502.     else if (ABS(values[1] - ABS(2.0 * 180.0 * ratan2(mouseX - (bounds[1] + bounds[0]) / 2.0,
  503.          mouseY - (bounds[2] + BOTTOMFUDGE)) / MY_PI)) < ANGLESLOP)
  504.     {
  505.     /* changing the perspective angle of view */
  506.     which = 1;
  507.     }
  508.     else /* default to moving the nearest clipping plane */
  509.     {
  510.     nearYPos = (int) (bounds[2] + BOTTOMFUDGE
  511.        + values[2] * ((bounds[3] - TOPFUDGE) - (bounds[2] + BOTTOMFUDGE))
  512.              / (MAXEYEDIST - MINEYEDIST));
  513.     farYPos = (int) (bounds[2] + BOTTOMFUDGE
  514.        + values[3] * ((bounds[3] - TOPFUDGE) - (bounds[2] + BOTTOMFUDGE))
  515.              / (MAXEYEDIST - MINEYEDIST));
  516.     if (ABS(mouseY - nearYPos) < ABS(mouseY - farYPos))
  517.     {
  518.         which = 2;
  519.         if (ABS(mouseY - nearYPos) > 3)
  520.         /* if more than 3 pixels away, snap line there */
  521.         {
  522.         saveValues[2] = (mouseY - (bounds[2] + BOTTOMFUDGE))
  523.                 / (((bounds[3] - TOPFUDGE)
  524.                    - (bounds[2] + BOTTOMFUDGE))
  525.                    / (MAXCLIP - MINCLIP) ) + MINCLIP;
  526.         }
  527.     }
  528.     else
  529.     {
  530.         which = 3;
  531.         if (ABS(mouseY - farYPos) > 3)
  532.         /* more than 3 pixels, snap */
  533.         {
  534.             saveValues[3] = (mouseY - (bounds[2] + BOTTOMFUDGE))
  535.                 / (((bounds[3] - TOPFUDGE)
  536.                    - (bounds[2] + BOTTOMFUDGE))
  537.                    / (MAXCLIP - MINCLIP) ) + MINCLIP;
  538.         }
  539.     }
  540.     }
  541.     SetVar(theControl, CURRENT, NewInt(which));
  542.     MakeMeCurrent(theControl);
  543.  
  544.     mXold = -1;
  545.     mYold = -1;
  546.  
  547.     /* track mouse */
  548.     while (Mouse(&mX, &mY))
  549.     {
  550.     /* if new values identical to old values, do squat */
  551.     if (mX == mXold && mY == mYold)
  552.     {
  553.         continue;
  554.     }
  555.     mXold = mX;
  556.     mYold = mY;
  557.  
  558.     if (hiResMode != ShiftDown())
  559.     /* state of shift-key changed */
  560.     {
  561.         hiResMode = ShiftDown();
  562.         for (i=0; i<4; ++i)
  563.         {
  564.         saveValues[i] = values[i];
  565.         }
  566.         mouseX = mX;
  567.         mouseY = mY;
  568.     }
  569.  
  570. #if 0
  571.     if (mX < bounds[0] - SLOP || mX > bounds[1] + SLOP    /* mouse outside rectangle */
  572.         || mY < bounds[2] - SLOP || mY > bounds[3] + SLOP) 
  573. #else
  574.     /* based only on x axis */
  575.     if (mX < bounds[0] - SLOP || mX > bounds[1] + SLOP)
  576. #endif
  577.     {
  578.         /* unhighlight here */
  579.         if ((int) hilites[which])
  580.         {
  581.         hilites[which] = false;
  582.         }
  583.         if (values[which] != oldValues[which])
  584.         {
  585.         for (i=0; i<4; ++i)
  586.             values[i] = oldValues[i];
  587.         }
  588.     }
  589.     else                    /* mouse inside rectangle */
  590.     {
  591.         /* highlight here */
  592.         if(! (int) hilites[which])
  593.         {
  594.         hilites[which] = true;
  595.         hilitesArray = NewRealArray(1, (long) 4);
  596.         CArray2Array(hilitesArray, hilites);
  597.         SetVar(theControl, HIGHLIGHTED, hilitesArray);
  598.         }
  599.  
  600.         deltaX = mX - mouseX;
  601.         deltaY = mY - mouseY;
  602.         switch(which)
  603.         {
  604.         case 0:
  605.                 values[0] = saveValues[0] + deltaY / (((bounds[3] - TOPFUDGE)
  606.                    - (bounds[2] + BOTTOMFUDGE))
  607.                    / (MAXEYEDIST - MINEYEDIST));
  608.             values[2] = values[0] + clipOff1;
  609.             values[3] = values[0] + clipOff2;
  610.             if (hiResMode)
  611.             {
  612.             values[0] = saveValues[0]+(values[0]-saveValues[0])/10;
  613.             values[2] = saveValues[2]+(values[2]-saveValues[2])/10;
  614.             values[3] = saveValues[3]+(values[3]-saveValues[3])/10;
  615.             }
  616.  
  617.             if (values[0] < MINEYEDIST)
  618.             values[0] = MINEYEDIST;
  619.             if (values[0] > MAXEYEDIST)
  620.             values[0] = MAXEYEDIST;
  621.  
  622.             if (values[2] < MINCLIP)
  623.             values[2] = MINCLIP;
  624.             if (values[2] > MAXCLIP)
  625.             values[2] = MAXCLIP;
  626.  
  627.             if (values[3] < MINCLIP)
  628.             values[3] = MINCLIP;
  629.             if (values[3] > MAXCLIP)
  630.             values[3] = MAXCLIP;
  631.  
  632.             break;
  633.         case 1:
  634.             if (ortho)
  635.             {
  636.             values[1] = ABS(MAXORTHOFOV *
  637.                 (mX - (bounds[0] + bounds[1])/2.0)
  638.                 / ( ((bounds[1]-SIDEFUDGE)-(bounds[0]+SIDEFUDGE)) / 2.0));
  639.         
  640.             if (hiResMode)
  641.                 values[1]=saveValues[1]+(values[1]-saveValues[1])/10;
  642.  
  643.             if (values[1] < MINORTHOFOV)
  644.                 values[1] = MINORTHOFOV;
  645.             if (values[1] > MAXORTHOFOV)
  646.                 values[1] = MAXORTHOFOV;
  647.             }
  648.             else
  649.             {
  650.             values[1] = 2.0 * 180.0 * ratan2(mX - (bounds[1] + bounds[0]) / 2.0,
  651.                             mY - (bounds[2] + BOTTOMFUDGE)) / MY_PI;
  652.             values[1] = values[1] < 0.0 ? -values[1] : values[1];
  653.             if (hiResMode)
  654.                 values[1]=saveValues[1]+(values[1]-saveValues[1])/10;
  655.  
  656.             if (values[1] < MINAOV)
  657.                 values[1] = MINAOV;
  658.             if (values[1] > MAXAOV)
  659.                 values[1] = MAXAOV;
  660.             }
  661.             break;
  662.  
  663.         case 2:
  664.                 values[2] = saveValues[2] + deltaY / (((bounds[3] - TOPFUDGE)
  665.                    - (bounds[2] + BOTTOMFUDGE))
  666.                    / (MAXCLIP - MINCLIP));
  667.             if (hiResMode)
  668.             values[2] = saveValues[2]+(values[2]-saveValues[2])/10;
  669.  
  670.             if (values[2] < MINCLIP)
  671.             values[2] = MINCLIP;
  672.             if (values[2] > MAXCLIP - MINCLIPDELTA)
  673.             values[2] = MAXCLIP - MINCLIPDELTA;
  674.             break;
  675.  
  676.         case 3:
  677.                 values[3] = saveValues[3] + deltaY / (((bounds[3] - TOPFUDGE)
  678.                    - (bounds[2] + BOTTOMFUDGE))
  679.                    / (MAXCLIP - MINCLIP));
  680.             if (hiResMode)
  681.             values[3] = saveValues[3] + (values[3]-saveValues[3])/10;
  682.  
  683.             if (values[3] < MINCLIP + MINCLIPDELTA)
  684.             values[3] = MINCLIP + MINCLIPDELTA;
  685.             if (values[3] > MAXCLIP)
  686.             values[3] = MAXCLIP;
  687.             break;
  688.         default:
  689.             ReportError("PressPerspecControl", "internal error!");
  690.             break;
  691.         }
  692.     }
  693.     /* if clip planes reversed, fix 'em */
  694.     if (values[3] < values[2])
  695.     {
  696.         tempvalue = values[2]; /* swap values */
  697.         values[2] = values[3];
  698.         values[3] = tempvalue;
  699.         tempvalue = hilites[2]; /* swap hilite flags */
  700.         hilites[2] = hilites[3];
  701.         hilites[3] = tempvalue;
  702.         tempvalue = oldValues[2]; /* swap old values, too */
  703.         oldValues[2] = oldValues[3];
  704.         oldValues[3] = tempvalue;
  705.         tempvalue = saveValues[2]; /* ..and the saved values */
  706.         saveValues[2] = saveValues[3];
  707.         saveValues[3] = tempvalue;
  708.         if (which == 3)
  709.         {
  710.         which = 2;      /* switch to other control part */
  711.         }
  712.         else if (which == 2)
  713.         {
  714.         which = 3;
  715.         }
  716.         SetVar(theControl, CURRENT, NewInt(which));
  717.     }
  718.     if (values[3] - values[2] < MINCLIPDELTA)
  719.     {
  720.         if (values[2] < MINCLIP + MINCLIPDELTA)
  721.         {
  722.         values[3] = values[2] + MINCLIPDELTA;
  723.         }
  724.         else if (values[3] > MAXCLIP - MINCLIPDELTA)
  725.         {
  726.         values[2] = values[3] - MINCLIPDELTA;
  727.         }
  728.         else
  729.         {
  730.         real ctr;
  731.  
  732.         ctr = (values[3] + values[2]) / 2.0;
  733.         values[2] = ctr - MINCLIPDELTA / 2.0;
  734.         values[3] = ctr + MINCLIPDELTA / 2.0;
  735.         }
  736.     }
  737.     valuesArray = NewRealArray (1, (long) 4);
  738.     CArray2Array(valuesArray, values);
  739.     SetVar(theControl, VALUE, valuesArray);
  740.     hilitesArray = NewRealArray (1, (long) 4);
  741.     CArray2Array(hilitesArray, hilites);
  742.     SetVar(theControl, HIGHLIGHTED, hilitesArray);
  743.     DrawMe(theControl);
  744.     ChangedValue(theControl);
  745.     }
  746.     hilites[0] = false;
  747.     hilites[1] = false;
  748.     hilites[2] = false;
  749.     hilites[3] = false;
  750.     hilitesArray = NewRealArray(1, (long) 4);
  751.     CArray2Array(hilitesArray, hilites);
  752.     SetVar(theControl, HIGHLIGHTED, hilitesArray);
  753.     ImInvalid(theControl);
  754.     ChangedValue(theControl);
  755.     if (logging) LogControl(theControl);
  756.  
  757.     return ObjTrue;
  758. #endif /* INTERACTIVE */
  759. }
  760.  
  761. ObjPtr KeyDownPerspecControl(theControl, key, flags)
  762. /* KEYDOWN event for PerspecControls */
  763. ObjPtr theControl;
  764. int key;
  765. long flags;
  766. {
  767. #ifdef INTERACTIVE
  768.     int        bounds[4];              /* meat of boundsArray */
  769.     ObjPtr    valuesArray;        /* array of data for complex control */
  770.     real    values[4];        /* meat of valuesArray */
  771.     real    oldValues[4];        /* old meat of valuesArray */
  772.     int        isChanged;              /* return value of changer */
  773.     ObjPtr    theWhich;        /* Int thing holding which control */
  774.     int        which;            /* which control part we're moving */
  775.  
  776.     if (!AmICurrent(theControl))
  777.     {
  778.     return ObjFalse;
  779.     }
  780.  
  781.     /* BORK temporary kludge */
  782.  
  783.     theWhich = GetIntVar("KeyDownPerspecControl", theControl, CURRENT);
  784.     if (!theWhich)
  785.     {
  786.     /* can't find what part is current */
  787.     return ObjFalse;
  788.     }
  789.  
  790.     which = GetInt(theWhich);
  791.     if (which < 0 || which > 3)
  792.     {
  793.     /* CURRENT value was invalid */
  794.     return ObjFalse;
  795.     }
  796.  
  797.     if (!Get2DIntBounds(theControl,&bounds[0],&bounds[1],&bounds[2],&bounds[3]))
  798.     {
  799.         return NULLOBJ;
  800.     }
  801.     valuesArray = GetFixedArrayVar("KeyDownPerspecControl", theControl, VALUE, 1, 4L);
  802.     if (valuesArray)
  803.     {
  804.     Array2CArray(values, valuesArray);
  805.     }
  806.     else
  807.     {
  808.         return ObjFalse;
  809.     }
  810.     switch(key)
  811.     {
  812.     case '\0':
  813.         if (logging) LogControl(theControl);
  814.         return ObjTrue;
  815.         break;
  816.     case FK_UP_ARROW:
  817.     case FK_RIGHT_ARROW:
  818.         switch(which)
  819.         {
  820.         case 0:
  821.                 values[0] = values[0] + PERSPECSCALE
  822.                         * (MAXEYEDIST - MINEYEDIST)
  823.                         / ((bounds[3] - TOPFUDGE)
  824.                         - (bounds[2] + BOTTOMFUDGE));
  825.             if (values[0] < MINEYEDIST)
  826.             values[0] = MINEYEDIST;
  827.             if (values[0] > MAXEYEDIST)
  828.             values[0] = MAXEYEDIST;
  829.             break;
  830.         case 1:
  831.             if (GetPredicate(theControl, ORTHO))
  832.             {
  833.             values[1] = values[1] + 0.2;
  834.             if (values[1] < MINORTHOFOV)
  835.                 values[1] = MINORTHOFOV;
  836.             if (values[1] > MAXORTHOFOV)
  837.                 values[1] = MAXORTHOFOV;
  838.             }
  839.             else
  840.             {
  841.             values[1] = values[1] + 0.5;
  842.             if (values[1] < MINAOV)
  843.                 values[1] = MINAOV;
  844.             if (values[1] > MAXAOV)
  845.                 values[1] = MAXAOV;
  846.             }
  847.             break;
  848.  
  849.         case 2:
  850.                 values[2] = values[2] + PERSPECSCALE
  851.                         * (MAXEYEDIST - MINEYEDIST)
  852.                         / ((bounds[3] - TOPFUDGE)
  853.                         - (bounds[2] + BOTTOMFUDGE));
  854.             if (values[2] < MINCLIP)
  855.             values[2] = MINCLIP;
  856.             if (values[2] > MAXCLIP)
  857.             values[2] = MAXCLIP;
  858.             break;
  859.  
  860.         case 3:
  861.                 values[3] = values[3] + PERSPECSCALE
  862.                         * (MAXEYEDIST - MINEYEDIST)
  863.                         / ((bounds[3] - TOPFUDGE)
  864.                         - (bounds[2] + BOTTOMFUDGE));
  865.             if (values[3] < MINCLIP)
  866.             values[3] = MINCLIP;
  867.             if (values[3] > MAXCLIP)
  868.             values[3] = MAXCLIP;
  869.             break;
  870.         default:
  871.             ReportError("KeyDownPerspecControl", "internal error!");
  872.             break;
  873.         }
  874.         break;
  875.     case FK_DOWN_ARROW:
  876.     case FK_LEFT_ARROW:
  877.         switch(which)
  878.         {
  879.         case 0:
  880.                 values[0] = values[0] - PERSPECSCALE
  881.                         * (MAXEYEDIST - MINEYEDIST)
  882.                         / ((bounds[3] - TOPFUDGE)
  883.                         - (bounds[2] + BOTTOMFUDGE));
  884.             if (values[0] < MINEYEDIST)
  885.             values[0] = MINEYEDIST;
  886.             if (values[0] > MAXEYEDIST)
  887.             values[0] = MAXEYEDIST;
  888.             break;
  889.         case 1:
  890.             if (GetPredicate(theControl, ORTHO))
  891.             {
  892.             values[1] = values[1] - 0.2;
  893.             if (values[1] < MINORTHOFOV)
  894.                 values[1] = MINORTHOFOV;
  895.             if (values[1] > MAXORTHOFOV)
  896.                 values[1] = MAXORTHOFOV;
  897.             }
  898.             else
  899.             {
  900.             values[1] = values[1] - 0.5;
  901.             if (values[1] < MINAOV)
  902.                 values[1] = MINAOV;
  903.             if (values[1] > MAXAOV)
  904.                 values[1] = MAXAOV;
  905.             }
  906.             break;
  907.  
  908.         case 2:
  909.                 values[2] = values[2] - PERSPECSCALE
  910.                         * (MAXEYEDIST - MINEYEDIST)
  911.                         / ((bounds[3] - TOPFUDGE)
  912.                         - (bounds[2] + BOTTOMFUDGE));
  913.             if (values[2] < MINCLIP)
  914.             values[2] = MINCLIP;
  915.             if (values[2] > MAXCLIP)
  916.             values[2] = MAXCLIP;
  917.             break;
  918.  
  919.         case 3:
  920.                 values[3] = values[3] - PERSPECSCALE
  921.                         * (MAXEYEDIST - MINEYEDIST)
  922.                         / ((bounds[3] - TOPFUDGE)
  923.                         - (bounds[2] + BOTTOMFUDGE));
  924.             if (values[3] < MINCLIP)
  925.             values[3] = MINCLIP;
  926.             if (values[3] > MAXCLIP)
  927.             values[3] = MAXCLIP;
  928.             break;
  929.         default:
  930.             ReportError("KeyDownPerspecControl", "internal error");
  931.             break;
  932.         }
  933.         break;
  934.     default:
  935.         if (F_SHIFTDOWN & flags)
  936.         {
  937.         MakePerspecOrtho(theControl, !GetPredicate(theControl, ORTHO));
  938.         }
  939.         return ObjTrue; /* acknowledge call, but ignore key */
  940.         break;
  941.     }
  942.     CArray2Array(valuesArray, values);
  943.     ImInvalid(theControl);
  944.     ChangedValue(theControl);
  945.     return ObjTrue;
  946. #endif /* INTERACTIVE */
  947. }
  948.  
  949. ObjPtr    SetPerspecControlValue(theControl, theNewValues)
  950. /* sets values on perspective control */
  951. ObjPtr    theControl, theNewValues;
  952. {
  953.     ObjPtr    theOldValues;
  954.     real    newValues[4], temp;
  955.     real    oldValues[4];
  956.     int        changed;
  957.     int        i;
  958.  
  959.     changed = false;
  960.     theOldValues = GetVar(theControl, VALUE);
  961.     if (!theOldValues)
  962.     {
  963.     changed = true;
  964.     }
  965.     else if (!IsArray(theOldValues))
  966.     {
  967.     changed = true;
  968.     }
  969.     else
  970.     {
  971.     Array2CArray(oldValues, theOldValues);
  972.     }
  973.     Array2CArray(newValues, theNewValues);
  974.     newValues[0] = newValues[0] < MINEYEDIST ? MINEYEDIST : newValues[0];
  975.     newValues[0] = newValues[0] > MAXEYEDIST ? MAXEYEDIST : newValues[0];
  976.     if (GetPredicate(theControl, ORTHO))
  977.     {
  978.     newValues[1] = newValues[1] < MINORTHOFOV ? MINORTHOFOV : newValues[1];
  979.     newValues[1] = newValues[1] > MAXORTHOFOV ? MAXORTHOFOV : newValues[1];
  980.     }
  981.     else
  982.     {
  983.     newValues[1] = newValues[1] < MINAOV ? MINAOV : newValues[1];
  984.     newValues[1] = newValues[1] > MAXAOV ? MAXAOV : newValues[1];
  985.     }
  986.     newValues[2] = newValues[2] < MINCLIP ? MINCLIP : newValues[2];
  987.     newValues[2] = newValues[2] > MAXCLIP ? MAXCLIP : newValues[2];
  988.     newValues[3] = newValues[3] < MINCLIP ? MINCLIP : newValues[3];
  989.     newValues[3] = newValues[3] > MAXCLIP ? MAXCLIP : newValues[3];
  990.     if (newValues[2] > newValues[3])
  991.     {
  992.     temp = newValues[2];
  993.     newValues[2] = newValues[3];
  994.     newValues[3] = temp;
  995.     }
  996.     for (i = 0; !changed && i < 4; ++i)
  997.     {
  998.     if (newValues[i] != oldValues[i])
  999.         changed = true;
  1000.     }
  1001.     CArray2Array(theNewValues, newValues);
  1002.     SetVar(theControl, VALUE, theNewValues);
  1003.     if (changed)
  1004.     {
  1005.     ImInvalid(theControl);
  1006.     ChangedValue(theControl);
  1007.     if (logging) LogControl(theControl);
  1008.     return ObjTrue;
  1009.     }
  1010.     if (logging) LogControl(theControl);
  1011.     return ObjFalse;
  1012. }
  1013.  
  1014. ObjPtr    GetPerspecControlValue(theControl, values)
  1015. ObjPtr    theControl;
  1016. real    values[4];
  1017. {
  1018.     ObjPtr    theValues;
  1019.     int        i;
  1020.  
  1021.     theValues = GetFixedArrayVar("GetPerspecControlValue", theControl, VALUE, 1, 4L);
  1022.     if (!theValues)
  1023.     {
  1024.     for (i=0;i<4;++i) values[i] = 0.0;
  1025.     return ObjFalse;
  1026.     }
  1027.  
  1028.     /* successful retrieval of values */
  1029.     Array2CArray(values, theValues);
  1030.     return ObjTrue;
  1031. }
  1032.  
  1033. #ifdef PROTO
  1034. Bool MakePerspecOrtho(ObjPtr control, Bool flag)
  1035. #else
  1036. Bool MakePerspecOrtho(control, flag)
  1037. ObjPtr control;
  1038. Bool flag;
  1039. #endif
  1040. {
  1041.     if (flag != GetPredicate(control, ORTHO))
  1042.     {
  1043.     ObjPtr valsArray;
  1044.     real vals[4];
  1045.     real dist, fov;        /* object distance, field of view */
  1046.     ObjPtr oldValue;
  1047.  
  1048.     SetVar(control, ORTHO, flag ? ObjTrue : ObjFalse);
  1049.     valsArray = GetFixedArrayVar("MakePerspecOrtho", control, VALUE, 1, 4L);
  1050.     Array2CArray(vals, valsArray);
  1051.     dist = vals[0];
  1052.     fov = vals[1];
  1053.     if (flag)
  1054.     {
  1055.         /* if control was perspec, is now ORTHO */
  1056.         /* obsolete?
  1057.         fov = (dist / rcos((fov / 2.0) * (MY_PI / 180.0)))
  1058.           * rsin((fov / 2.0) * (MY_PI / 180.0));
  1059.         */
  1060.         oldValue = GetVar(control, OLDVALUE);
  1061.         if (oldValue)
  1062.         {
  1063.         fov = GetReal(oldValue);
  1064.         }
  1065.         else
  1066.         {
  1067.         fov = INITFOV;
  1068.         }
  1069.  
  1070.         if (fov < 0.0)
  1071.         fov = -fov;
  1072.         if (fov > MAXORTHOFOV)
  1073.         fov = MAXORTHOFOV;
  1074.     }
  1075.     else
  1076.     {
  1077.         /* control was ORTHO, is now perspec again */
  1078.         oldValue = GetVar(control, OLDVALUE);
  1079.         if (oldValue)
  1080.         {
  1081.         fov = GetReal(oldValue);
  1082.         }
  1083.         else
  1084.         {
  1085.         fov = INITAOV;
  1086.         }
  1087.     }
  1088.  
  1089.     SetVar(control, OLDVALUE, NewReal(vals[1]));
  1090.     vals[1] = fov;
  1091.     CArray2Array(valsArray, vals);
  1092.     ChangedValue(control);
  1093.     ImInvalid(control);
  1094.     return true;
  1095.     }
  1096.     else
  1097.     {
  1098.     return false;
  1099.     }
  1100. }
  1101.  
  1102. void    InitPerspecControls()
  1103. /* sets up perspective controls stuff */
  1104. {
  1105.     perspecControlClass = NewObject(controlClass, 0);
  1106.     AddToReferenceList((ThingPtr) perspecControlClass);
  1107.     SetMethod(perspecControlClass, DRAW, DrawPerspecControl);
  1108.     SetMethod(perspecControlClass, PRESS, PressPerspecControl);
  1109.     SetMethod(perspecControlClass, SETVAL, SetPerspecControlValue);
  1110.     SetMethod(perspecControlClass, GETVAL, GetPerspecControlValue);
  1111.     SetMethod(perspecControlClass, KEYDOWN, KeyDownPerspecControl);
  1112.     SetVar(perspecControlClass, COLOR, NewInt(UIBACKGROUND));
  1113.     SetVar(perspecControlClass, WHICHICON, NewInt(ICONOBSERVER));
  1114.     SetVar(perspecControlClass, TYPESTRING, NewString("perspective control"));
  1115.     SetVar(perspecControlClass, HELPSTRING, NewString(
  1116. "This control affects the perspective view in the Space. Clicking and \
  1117. dragging the central cube object will move the viewed fields towards or \
  1118. away from the Eye. You can move the front and back clipping planes by \
  1119. clicking on and dragging the two horizontal lines. Clicking and \
  1120. dragging either of the two diagonal lines will change the angle of view."));
  1121. }
  1122.  
  1123. void    KillPerspecControls()
  1124. /* unsets-up perspective controls stuff */
  1125. {
  1126.     RemoveFromReferenceList(perspecControlClass);
  1127.     perspecControlClass = 0;
  1128. }
  1129.  
  1130. #define XFUDGE -4.0
  1131. #define YFUDGE -7.0
  1132.  
  1133. ObjPtr    NewPerspecControl(left, right, bottom, top, name)
  1134. int    left, right, bottom, top;
  1135. char *name;
  1136. /*Makes a new panel with bounds left, right, bottom, top, and label label*/
  1137. {
  1138.     real    values[4], hilites[4];
  1139.     ObjPtr    valuesArray, hilitesArray;
  1140.     ObjPtr    retVal;
  1141.     ObjPtr    labelPtr;
  1142.     ObjPtr    hilightPtr;
  1143.     real    loc[2];
  1144.     ObjPtr    locArray;
  1145.  
  1146.     values[0] = INITEYEDIST;
  1147.     values[1] = INITAOV;
  1148.     values[2] = INITNEARCLIP;
  1149.     values[3] = INITFARCLIP;
  1150.  
  1151.     hilites[0] = false;
  1152.     hilites[1] = false;
  1153.     hilites[2] = false;
  1154.     hilites[3] = false;
  1155.  
  1156.     loc[0] = XFUDGE;
  1157.     loc[1] = YFUDGE;
  1158.  
  1159.     valuesArray = NewRealArray(1, (long) 4);
  1160.     hilitesArray = NewRealArray(1, (long) 4);
  1161.     locArray = NewRealArray(1, (long) 2);
  1162.     retVal = NewObject(perspecControlClass, 0);
  1163.     if (valuesArray && hilitesArray && retVal)
  1164.     {
  1165.         CArray2Array(valuesArray, values);
  1166.     SetVar(retVal, VALUE, (ThingPtr) valuesArray);
  1167.  
  1168.     CArray2Array(hilitesArray, hilites);
  1169.     SetVar(retVal, HIGHLIGHTED, (ThingPtr) hilitesArray);
  1170.  
  1171.     CArray2Array(locArray, loc);
  1172.     SetVar(retVal, ICONLOC, locArray);
  1173.  
  1174.     Set2DIntBounds(retVal, left, right, bottom, top);
  1175.     SetVar(retVal, NAME, NewString(name));
  1176.     SetVar(retVal, ORTHO, ObjFalse);
  1177.     return retVal;
  1178.     }
  1179.     else
  1180.     {
  1181.     return NULLOBJ;
  1182.     }
  1183. }
  1184.